﻿using System;
using System.ComponentModel;
using System.IO;
using System.Net;
using System.Security.Cryptography.X509Certificates;
using System.Text;

namespace LdCms.Common.Web.Http
{
    using LdCms.Common.Extension;
    using LdCms.Common.Utility;
    using Microsoft.AspNetCore.Http.Internal;
    using System.Drawing;

    public class HttpRequestUtilities
    {
        private int timeout = 19600;
        private string codeType = "utf-8";
        private HttpRequestEnum.Method method = HttpRequestEnum.Method.GET;
        private HttpRequestEnum.ContentType contentType = HttpRequestEnum.ContentType.UrlEncoded;
        public int Timeout
        {
            get
            {
                return timeout;
            }
            set
            {
                timeout = value;
            }
        }
        public string CodeType
        {
            get
            {
                return codeType;
            }
            set
            {
                codeType = value;
            }
        }
        public HttpRequestEnum.Method Method
        {
            get
            {
                return method;
            }
            set
            {
                method = value;
            }
        }
        public HttpRequestEnum.ContentType ContentType
        {
            get
            {
                return contentType;
            }
            set
            {
                contentType = value;
            }
        }

        public string RequestInputStream()
        {
            try
            {
                HttpContext.Current.Request.EnableRewind();
                HttpContext.Current.Request.Body.Seek(0, 0);
                Stream stream = HttpContext.Current.Request.Body;
                bool isContentLength = HttpContext.Current.Request.ContentLength.HasValue;
                if (!isContentLength)
                    return string.Empty;
                byte[] buffer = new byte[HttpContext.Current.Request.ContentLength.Value];
                stream.Read(buffer, 0, buffer.Length);
                return Encoding.UTF8.GetString(buffer);
            }
            catch (Exception ex)
            {
                throw new Exception(ex.Message);
            }
        }
        public string GetToUrl(string url)
        {
            try
            {
                Method = HttpRequestEnum.Method.GET;
                ContentType = HttpRequestEnum.ContentType.UrlEncoded;
                HttpWebResponse hwrs = HttpWebResponse(url, Method, ContentType);
                Stream getStream = hwrs.GetResponseStream();
                return StreamToStr(getStream, hwrs.CharacterSet);
            }
            catch (Exception ex)
            {
                throw new Exception(ex.Message);
            }
        }
        public string GetToUrl(string url, string codeType)
        {
            try
            {
                Method = HttpRequestEnum.Method.GET;
                ContentType = HttpRequestEnum.ContentType.UrlEncoded;
                HttpWebResponse hwrs = HttpWebResponse(url, Method, ContentType);
                Stream getStream = hwrs.GetResponseStream();
                return StreamToStr(getStream, hwrs.CharacterSet);
            }
            catch (Exception ex)
            {
                throw new Exception(ex.Message);
            }
        }

        public string PostToUrl(string url)
        {
            try
            {
                Method = HttpRequestEnum.Method.POST;
                ContentType = HttpRequestEnum.ContentType.UrlEncoded;
                HttpWebResponse hwrs = HttpWebResponse(url, Method, ContentType);
                Stream getStream = hwrs.GetResponseStream();
                return StreamToStr(getStream, hwrs.CharacterSet);
            }
            catch (Exception ex)
            {
                throw new Exception(ex.Message);
            }
        }
        public string PostToUrl(string url, string data)
        {
            try
            {
                Method = HttpRequestEnum.Method.POST;
                HttpWebResponse hwrs = HttpWebResponse(url, Method, data);
                Stream getStream = hwrs.GetResponseStream();
                //111  = "image/jpeg";
                string contentType = hwrs.ContentType;
                if (contentType == "image/jpeg")
                    return StreamToImgBase64Str(getStream);
                else
                    return StreamToStr(getStream, hwrs.CharacterSet); 
            }
            catch (Exception ex)
            {
                throw new Exception(ex.Message);
            }
        }
        public string PostToUrl(string url, HttpRequestEnum.ContentType contentType, string data)
        {
            try
            {
                Method = HttpRequestEnum.Method.POST;
                HttpWebResponse hwrs = HttpWebResponse(url, Method, contentType, data);
                Stream getStream = hwrs.GetResponseStream();
                return StreamToStr(getStream, hwrs.CharacterSet);
            }
            catch (Exception ex)
            {
                throw new Exception(ex.Message);
            }
        }
        public string PostToUrl(string url, X509Certificate2 cert, string data)
        {
            try
            {
                Method = HttpRequestEnum.Method.POST;
                ContentType = HttpRequestEnum.ContentType.UrlEncoded;
                HttpWebResponse hwrs = HttpWebResponse(url, Method, ContentType, cert, data);
                Stream getStream = hwrs.GetResponseStream();
                return StreamToStr(getStream, hwrs.CharacterSet);
            }
            catch (Exception ex)
            {
                throw new Exception(ex.Message);
            }
        }

        public string PutToUrl(string url, string data)
        {
            try
            {
                Method = HttpRequestEnum.Method.PUT;
                ContentType = HttpRequestEnum.ContentType.UrlEncoded;
                HttpWebResponse hwrs = HttpWebResponse(url, Method, ContentType, data);
                Stream getStream = hwrs.GetResponseStream();
                return StreamToStr(getStream, hwrs.CharacterSet);
            }
            catch (Exception ex)
            {
                throw new Exception(ex.Message);
            }
        }
        public string PutToUrl(string url, HttpRequestEnum.ContentType contentType, string data)
        {
            try
            {
                Method = HttpRequestEnum.Method.PUT;
                HttpWebResponse hwrs = HttpWebResponse(url, Method, contentType, data);
                Stream getStream = hwrs.GetResponseStream();
                return StreamToStr(getStream, hwrs.CharacterSet);
            }
            catch (Exception ex)
            {
                throw new Exception(ex.Message);
            }
        }
        public string PatchToUrl(string url, string data)
        {
            try
            {
                Method = HttpRequestEnum.Method.PATCH;
                ContentType = HttpRequestEnum.ContentType.UrlEncoded;
                HttpWebResponse hwrs = HttpWebResponse(url, Method, ContentType, data);
                Stream getStream = hwrs.GetResponseStream();
                return StreamToStr(getStream, hwrs.CharacterSet);
            }
            catch (Exception ex)
            {
                throw new Exception(ex.Message);
            }
        }
        public string PatchToUrl(string url, HttpRequestEnum.ContentType contentType, string data)
        {
            try
            {
                Method = HttpRequestEnum.Method.PATCH;
                HttpWebResponse hwrs = HttpWebResponse(url, Method, contentType, data);
                Stream getStream = hwrs.GetResponseStream();
                return StreamToStr(getStream, hwrs.CharacterSet);
            }
            catch (Exception ex)
            {
                throw new Exception(ex.Message);
            }
        }
        public string DeleteToUrl(string url)
        {
            try
            {
                Method = HttpRequestEnum.Method.DELETE;
                ContentType = HttpRequestEnum.ContentType.UrlEncoded;
                HttpWebResponse hwrs = HttpWebResponse(url, Method);
                Stream getStream = hwrs.GetResponseStream();
                return StreamToStr(getStream, hwrs.CharacterSet);
            }
            catch (Exception ex)
            {
                throw new Exception(ex.Message);
            }
        }

        public string GetFileToUrl(string url, string savePath)
        {
            try
            {
                Method = HttpRequestEnum.Method.GET;
                ContentType = HttpRequestEnum.ContentType.UrlEncoded;
                HttpWebResponse hwrs = HttpWebResponse(url, Method, ContentType);

                string tempFile = CreateTempFilePath(savePath);
                byte[] fileBytes = new byte[hwrs.ContentLength];
                using (Stream stream = hwrs.GetResponseStream())
                {
                    using (FileStream fs = new FileStream(tempFile, FileMode.Append, FileAccess.Write, FileShare.ReadWrite))
                    {
                        int size = stream.Read(fileBytes, 0, (int)fileBytes.Length);
                        while (size > 0)
                        {
                            fs.Write(fileBytes, 0, size);
                            size = stream.Read(fileBytes, 0, (int)fileBytes.Length);
                        }
                        fs.Close();
                    }
                }
                string file = string.Format("{0}\\{1}", Utility.AppRoot(), savePath);
                if (Net.FileHelper.IsFile(file))
                    Net.FileHelper.DeleteFile(file);
                System.IO.File.Move(tempFile, file);
                return savePath;
            }
            catch (Exception ex)
            {
                throw new Exception(ex.Message);
            }
        }
        public string PostFileToUrl(string url, string filePath)
        {
            try
            {
                string postData = string.Empty;
                string fileName = string.Empty;
                HttpWebResponse hwrs = HttpWebResponse(url, postData, fileName, filePath);
                Stream getStream = hwrs.GetResponseStream();
                return StreamToStr(getStream, hwrs.CharacterSet);
            }
            catch (Exception ex)
            {
                throw new Exception(ex.Message);
            }
        }
        public string PostFileToUrl(string url, string headerName, string filePath)
        {
            try
            {
                string postData = string.Empty;
                HttpWebResponse hwrs = HttpWebResponse(url, postData, headerName, filePath);
                Stream getStream = hwrs.GetResponseStream();
                return StreamToStr(getStream, hwrs.CharacterSet);
            }
            catch (Exception ex)
            {
                throw new Exception(ex.Message);
            }
        }
        public string PostFileToUrl(string url, string data, string headerName, string filePath)
        {
            try
            {
                HttpWebResponse hwrs = HttpWebResponse(url, data, headerName, filePath);
                Stream getStream = hwrs.GetResponseStream();
                return StreamToStr(getStream, hwrs.CharacterSet);
            }
            catch (Exception ex)
            {
                throw new Exception(ex.Message);
            }
        }

        public string HttpRequest(string url, HttpRequestEnum.Method method, HttpRequestEnum.ContentType contentType)
        {
            try
            {
                HttpWebResponse hwrs = HttpWebResponse(url, method, contentType);
                Stream getStream = hwrs.GetResponseStream();
                return StreamToStr(getStream, hwrs.CharacterSet);
            }
            catch (Exception ex)
            {
                throw new Exception(ex.Message);
            }
        }
        public string HttpRequest(string url, HttpRequestEnum.Method method, HttpRequestEnum.ContentType contentType, string postData)
        {
            try
            {
                HttpWebResponse hwrs = HttpWebResponse(url, method, contentType, postData);
                Stream getStream = hwrs.GetResponseStream();
                return StreamToStr(getStream, hwrs.CharacterSet);
            }
            catch (Exception ex)
            {
                throw new Exception(ex.Message);
            }
        }
        public string HttpRequest(string url, HttpRequestEnum.Method method, HttpRequestEnum.ContentType contentType, string postData, string codeType)
        {
            try
            {
                HttpWebResponse hwrs = HttpWebResponse(url, method, contentType, postData);
                Stream getStream = hwrs.GetResponseStream();
                return StreamToStr(getStream, hwrs.CharacterSet);
            }
            catch (Exception ex)
            {
                throw new Exception(ex.Message);
            }
        }
        public HttpWebResponse HttpResponse(string url, HttpRequestEnum.Method method, HttpRequestEnum.ContentType contentType, string postData, string codeType)
        {
            try
            {
                return HttpWebResponse(url, method, contentType, postData);
            }
            catch (Exception ex)
            {
                throw new Exception(ex.Message);
            }
        }


        private HttpWebResponse HttpWebResponse(string url, HttpRequestEnum.Method method)
        {
            try
            {
                HttpWebRequest hwr = (HttpWebRequest)WebRequest.Create(url);
                hwr.Timeout = Timeout;
                hwr.Method = method.ToString();
                return (HttpWebResponse)hwr.GetResponse();
            }
            catch (Exception ex)
            {
                throw new Exception(ex.Message);
            }
        }
        private HttpWebResponse HttpWebResponse(string url, HttpRequestEnum.Method method, string postData)
        {
            try
            {
                HttpWebRequest hwr = (HttpWebRequest)WebRequest.Create(url);
                hwr.Timeout = Timeout;
                hwr.Method = method.ToString();
                hwr.ContentType = GetContentType(ContentType);
                byte[] bs = StrToBytes(postData, CodeType);
                hwr.ContentLength = bs.Length;
                using (Stream reqStream = hwr.GetRequestStream())
                {
                    reqStream.Write(bs, 0, bs.Length);
                    reqStream.Close();
                }

                return (HttpWebResponse)hwr.GetResponse();
            }
            catch (Exception ex)
            {
                throw new Exception(ex.Message);
            }
        }
        private HttpWebResponse HttpWebResponse(string url, HttpRequestEnum.Method method, X509Certificate2 cert, string postData)
        {
            try
            {
                HttpWebRequest hwr = (HttpWebRequest)WebRequest.Create(url);
                hwr.ClientCertificates.Add(cert);
                hwr.Timeout = Timeout;
                hwr.Method = method.ToString();
                hwr.ContentType = GetContentType(ContentType);
                byte[] bs = StrToBytes(postData, CodeType);
                hwr.ContentLength = bs.Length;
                using (Stream reqStream = hwr.GetRequestStream())
                {
                    reqStream.Write(bs, 0, bs.Length);
                    reqStream.Close();
                }
                return (HttpWebResponse)hwr.GetResponse();
            }
            catch (Exception ex)
            {
                throw new Exception(ex.Message);
            }
        }
        private HttpWebResponse HttpWebResponse(string url, HttpRequestEnum.Method method, HttpRequestEnum.ContentType contentType)
        {
            try
            {
                HttpWebRequest hwr = (HttpWebRequest)WebRequest.Create(url);
                hwr.Timeout = Timeout;
                hwr.Method = method.ToString();
                hwr.ContentType = GetContentType(contentType);
                return (HttpWebResponse)hwr.GetResponse();
            }
            catch (Exception ex)
            {
                throw new Exception(ex.Message);
            }
        }
        private HttpWebResponse HttpWebResponse(string url, HttpRequestEnum.Method method, HttpRequestEnum.ContentType contentType, string postData)
        {
            try
            {
                HttpWebRequest hwr = (HttpWebRequest)WebRequest.Create(url);
                hwr.Timeout = Timeout;
                hwr.Method = method.ToString();
                byte[] bs = StrToBytes(postData, CodeType);
                hwr.ContentType = GetContentType(contentType);
                hwr.ContentLength = bs.Length;
                using (Stream reqStream = hwr.GetRequestStream())
                {
                    reqStream.Write(bs, 0, bs.Length);
                    reqStream.Close();
                }
                return (HttpWebResponse)hwr.GetResponse();
            }
            catch (Exception ex)
            {
                throw new Exception(ex.Message);
            }
        }
        private HttpWebResponse HttpWebResponse(string url, HttpRequestEnum.Method method, HttpRequestEnum.ContentType contentType, X509Certificate2 cert, string postData)
        {
            try
            {
                HttpWebRequest hwr = (HttpWebRequest)WebRequest.Create(url);
                hwr.ClientCertificates.Add(cert);
                hwr.Timeout = Timeout;
                hwr.Method = method.ToString();
                hwr.ContentType = GetContentType(contentType);
                byte[] bs = StrToBytes(postData, CodeType);
                hwr.ContentLength = bs.Length;
                using (Stream reqStream = hwr.GetRequestStream())
                {
                    reqStream.Write(bs, 0, bs.Length);
                    reqStream.Close();
                }
                return (HttpWebResponse)hwr.GetResponse();
            }
            catch (Exception ex)
            {
                throw new Exception(ex.Message);
            }
        }
        private HttpWebResponse HttpWebResponse(string url, string postData, string fileName, string filePath)
        {
            try
            {
                HttpWebRequest hwr = (HttpWebRequest)WebRequest.Create(url);
                hwr.Timeout = Timeout;
                hwr.Method = HttpRequestEnum.Method.POST.ToString();

                //POST 文件
                string boundary = DateTime.Now.Ticks.ToString("X");                                              // 随机分隔线
                byte[] item_boundary_bytes = Encoding.UTF8.GetBytes(string.Format("\r\n--{0}\r\n", boundary));   // 开始boundary
                byte[] post_header_bytes = Encoding.UTF8.GetBytes(StringBuilderHeader(fileName, filePath));      // 头部boundary
                byte[] file_bytes = FileBytes(filePath);                                                         // 文件byte
                byte[] post_data = StrToBytes(postData, "utf-8");                                                // 内容byte
                byte[] end_boundary_bytes = Encoding.UTF8.GetBytes(string.Format("\r\n--{0}--\r\n", boundary));  // 结束boundary

                hwr.ContentType = string.Format("multipart/form-data;charset=utf-8;boundary={0}", boundary);
                using (Stream postStream = hwr.GetRequestStream())
                {
                    postStream.Write(item_boundary_bytes, 0, item_boundary_bytes.Length);
                    postStream.Write(post_header_bytes, 0, post_header_bytes.Length);
                    postStream.Write(file_bytes, 0, file_bytes.Length);
                    postStream.Write(post_data, 0, post_data.Length);
                    postStream.Write(end_boundary_bytes, 0, end_boundary_bytes.Length);
                    postStream.Close();
                }
                return (HttpWebResponse)hwr.GetResponse();
            }
            catch (Exception ex)
            {
                throw new Exception(ex.Message);
            }
        }


        private byte[] StreamToBytes(Stream stream)
        {
            byte[] bytes = new byte[stream.Length];
            stream.Read(bytes, 0, bytes.Length);
            // 设置当前流的位置为流的开始 
            stream.Seek(0, SeekOrigin.Begin);
            return bytes;
        }
        private Stream BytesToStream(byte[] bytes)
        {
            Stream stream = new MemoryStream(bytes);
            return stream;
        }
        private byte[] StrToBytes(string str, string codeType)
        {
            Encoding encoding = Encoding.GetEncoding(codeType);
            return encoding.GetBytes(str);
        }
        private string StreamToStr(Stream instream, string codeType)
        {
            string characterSet = string.IsNullOrWhiteSpace(codeType) ? this.codeType : codeType;
            StreamReader sr = new StreamReader(instream, Encoding.GetEncoding(characterSet));
            return sr.ReadToEnd();
        }
        private string StreamToImgBase64Str(Stream instream)
        {
            try
            {
                MemoryStream ms = new MemoryStream();
                byte[] buffer = new byte[1024];
                while (true)
                {
                    int sz = instream.Read(buffer, 0, 1024);
                    if (sz == 0) break;
                    ms.Write(buffer, 0, sz);
                }
                Image img = Image.FromStream(ms);
                Bitmap bitmap = new Bitmap(img);
                return Common.Image.ImageHelper.BitmapToBase64String(bitmap);
            }
            catch (Exception ex)
            {
                throw new Exception(ex.Message);
            }
        }

        private string GetContentType(HttpRequestEnum.ContentType contentType)
        {
            string result = string.Empty;
            Type type = typeof(HttpRequestEnum.ContentType);
            foreach (System.Reflection.MemberInfo mInfo in type.GetMembers())
            {
                foreach (Attribute attr in Attribute.GetCustomAttributes(mInfo))
                {
                    if (attr.GetType() == typeof(DescriptionAttribute))
                    {
                        if (mInfo.Name == contentType.ToString())
                        {
                            result = ((DescriptionAttribute)attr).Description;
                        }
                    }
                }
            }
            return string.Format("{0};charset={1}", result, CodeType);//?charset={1}
        }
        private string StringBuilderHeader(string name, string filePath)
        {
            //请求头部信息 
            int pos = filePath.LastIndexOf("\\");
            string file_name = filePath.Substring(pos + 1);
            StringBuilder sb_header = new StringBuilder(string.Format("Content-Disposition:form-data;name=\"{0}\";filename=\"{1}\"\r\nContent-Type:application/octet-stream\r\n\r\n", name, file_name));
            return sb_header.ToString();
        }
        private byte[] FileBytes(string filePath)
        {
            FileStream fs = new FileStream(filePath, FileMode.Open, FileAccess.Read);
            byte[] bArr = new byte[fs.Length];
            fs.Read(bArr, 0, bArr.Length);
            fs.Close();
            return bArr;
        }
        private string CreateTempFilePath(string saveFile)
        {
            try
            {
                //指定虚拟路径
                string savePath = string.Format("{0}\\{1}", Utility.AppRoot(), saveFile);
                string filePath = System.IO.Path.GetDirectoryName(savePath);            //获取路径文件夹
                string fileName = System.IO.Path.GetFileName(savePath);                 //获取文件名
                string tempPath = string.Format("{0}\\temp", filePath);                 //临时文件夹
                string tempFile = string.Format("{0}\\{1}.temp", tempPath, fileName);   //临时文件
                                                                                        //判断文件夹是否存在，不存在创建临时文件目录
                if (!System.IO.Directory.Exists(tempPath))
                    System.IO.Directory.CreateDirectory(tempPath);
                //判断文件是否存在，存在则删除
                if (System.IO.File.Exists(tempFile))
                    System.IO.File.Delete(tempFile);
                return tempFile;
            }
            catch (Exception ex)
            {
                throw new Exception(ex.Message);
            }
        }

    }
}
